import { PageLoading } from '@ant-design/pro-layout';
import { history, addLocale, request as requestURL } from 'umi';
import _ from "lodash";
import RightContent from '@/components/RightContent';
import Footer from '@/components/Footer';
import { currentUser as queryCurrentUser } from './pages/user/Login/service';
import { message } from 'antd';
const loginPath = '/user/login';

const noNeedLoginRoutes = [
  "/user/login",
  "/diagnose/detail",
  "/diagnose/custom/pannel",
]

const isNeedLogin = function (path) {
  return !noNeedLoginRoutes.find(item => path.startsWith(item))
}

const errorHandler = function (error) {
  if (error.response) {
    if (typeof (error.data.message) == "object") {
      message.error(Object.values(error.data.message))
    }
    else {
      if (error.data.message) {
        message.error(error.data.message);
      } else if (error.data.msg) {
        message.error(error.data.msg);
      }
    }
  } else {
    message.error(error.message);
  }
  throw error;
};

export const request = {
  errorHandler,
}

/** 获取用户信息比较慢的时候会展示一个 loading */
export const initialStateConfig = {
  loading: <PageLoading />,
};
/**
 * @see  https://umijs.org/zh-CN/plugins/plugin-initial-state
 * */

export async function getInitialState() {
  const fetchUserInfo = async (userId, token) => {
    try {
      const msg = await queryCurrentUser(userId, token);
      if (msg.code !== 200) {
        // history.push(loginPath);
        return undefined;
      }
      const userInfo = { avatar: 'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png', ...msg.data };
      return userInfo;
    } catch (error) {
      // history.push(loginPath);
    }

    return undefined;
  }; // 如果是登录页面，不执行

  if (isNeedLogin(history.location.pathname)) {
    const userId = localStorage.getItem('userId');
    const token = localStorage.getItem('token');
    if (!token || !userId) {
      history.push(loginPath)
    } else {
      const currentUser = await fetchUserInfo(userId, token);
      return {
        fetchUserInfo,
        currentUser,
        settings: {},
      };
    }
  }
  return {
    fetchUserInfo,
    settings: {},
  };
} // ProLayout 支持的api https://procomponents.ant.design/components/layout

// https://procomponents.ant.design/components/layout/#%E5%92%8C-umi-%E4%B8%80%E8%B5%B7%E4%BD%BF%E7%94%A8
export const layout = ({ initialState }) => {
  return {
    rightContentRender: () => <RightContent />,
    disableContentMargin: false,
    waterMarkProps: {
      content: initialState?.currentUser?.username,
    },
    footerRender: () => <Footer />,
    onPageChange: () => {
      const { location } = history; // 如果没有登录，重定向到 login

      if (!initialState?.currentUser && isNeedLogin(location.pathname)) {
        history.push(loginPath);
      }
    },
    menuHeaderRender: undefined,
    ...initialState?.settings,
  };
};


let extraGrafanaRoutes = [];
let extraDiagnoseRoute = [];
let extraAppObserverRoute = [];
// Saved menu_name -> service_name
// @see menuName => config/routes.js
// @see servierName => /api/v1/services/list
let menuNameMapServiceName = {
  user: "sysom_api",
  welcome: "sysom_api",
  host: "sysom_api",
  journal: "sysom_api",
  monitor: "sysom_monitor_server",
  vmcore: "sysom_vmcore",
  diagnose: "sysom_diagnosis",
  migrate: "sysom_migration",
  security: "sysom_vul",
  hotfix: "sysom_hotfix",
  alarm: "sysom_alarm",
}
let enable_services = [];

/**
 *
 * @param {*} routes
 * @param {*} newRoute eg. /diagnose/cpu/schedmoni
 */
function addRoute(routes, newRoute, component) {
  console.log(`Add route ${newRoute}`);
  let rootPath = routes.find((item) => item.path == "/");
  // filter(Boolean) is used to remove the empty string at the start
  const parts = newRoute.split("/").filter(Boolean);
  const paths = parts.reduce((acc, part, index) => {
    const prevPath = index > 0 ? acc[index - 1] : '';
    acc.push(prevPath + '/' + part);
    return acc;
  }, []);

  let currentParent = rootPath;

  // Add /diagnose, /diagnose/cpu if not exist
  paths.forEach((path, index) => {
    if (index < paths.length - 1) {
      if (!_.keyBy(currentParent.routes, 'path')[path]) {
        currentParent.routes.push({
          path: path,
          name: parts[index],
          routes: [],
          routes: [{
            exact: true,
            path: path,
            redirect: paths[index + 1],
          }],
        });
        console.log("redirect", {
          path: path,
          redirect: paths[index + 1],
        })
      }
      currentParent = _.keyBy(currentParent.routes, 'path')[path];
    }
  });

  // Add /diagnose/cpu/schedmoni
  if (!_.keyBy(currentParent.routes, 'path')[newRoute]) {
    currentParent.routes.push({
      path: newRoute,
      name: parts[parts.length - 1],
      component: component
    });
  }
}

export function patchRoutes({ routes }) {
  let rootPath = routes.find((item) => item.path == "/");

  //Insert the grafana dashboard item to monitor memu.
  rootPath.routes.find((item) => item.name == "monitor")
    .routes.splice(-1, 0, ...extraGrafanaRoutes)

  // Add diagnose routes
  extraDiagnoseRoute.forEach(item => {
    addRoute(routes, item.path, item.component)
  });

  // Add app_observer routes
  extraAppObserverRoute.forEach(item => {
    addRoute(routes, item.path, item.component)
  });

  // Filter the menu by enable_services
  if (enable_services.length > 0) {
    rootPath.routes = rootPath.routes.filter(v => !menuNameMapServiceName[v.name] || enable_services.find(v2 => v2 == menuNameMapServiceName[v.name]))
  }
}

import grafanaDash from './pages/Monitor/grafana'
import diagnose_component from './pages/diagnose/diagnose';
import appobserver_component from './pages/app_observable';

export function render(oldRender) {
  //Add Grafana dashboard dynamically
  requestURL('/api/v1/monitor/grafana/search')
    .then((res) => {
      if (res["code"] != 0) {
        return Promise.reject(res["err"])
      }
      let datas = res["data"]
      //Tranfrom from grafana folder&dashboard list to antd route tree.
      extraGrafanaRoutes = datas.filter((i) => i.type == "dash-folder")
        .map((folder) => {
          //Add the title to locales to aviod initl FormattedMessage warning in antd core.
          addLocale('zh-CN', { [`menu.monitor.${folder.title}`]: folder.title })
          return {
            path: `/monitor/${folder.uid}`,
            name: folder.title,
            routes: datas.filter((i) => i.type == "dash-db" && i.folderId == folder.id)
              .map((dash) => {
                addLocale('zh-CN', { [`menu.monitor.${folder.title}.${dash.title}`]: dash.title })
                return {
                  name: dash.title,
                  path: `/monitor/${folder.uid}${dash.url}`,
                  component: grafanaDash
                }
              })
          }
        })
      return Promise.resolve()
    })
    .catch(err => {
      message.error("Grafana doesn't work!")
      return Promise.resolve()
    })
    .then(() => {
      return requestURL('/resource/diagnose/v2/locales.json')
    })
    .then((res) => {
      // 1. Add diagnoses locales
      Object.entries(res["locales"]).map(item => {
        if (item[0] != "version") {
          addLocale(item[0], item[1]);
        }
      });

      // 2. Add diagnoses menu and components
      extraDiagnoseRoute = [];
      res["menus"].forEach(item => {
        // menu.diagnose.memory.memgraph
        let configPath = item.split('.');
        // diagnose.memory.memgraph
        configPath.shift();
        console.log(configPath);
        extraDiagnoseRoute.push({
          path: `/${configPath.join('/')}`,
          component: diagnose_component
        })
      });
      return requestURL("/resource/app_observable/v1/locales.json");
    })
    .then((res) => {
      // 1. Add app_observer locales
      Object.entries(res["locales"]).map(item => {
        if (item[0] != "version") {
          addLocale(item[0], item[1]);
        }
      });

      // 2. Add app_observer menu and components
      extraAppObserverRoute = [];
      res["menus"].forEach(item => {
        // menu.app_observable.ntopo
        let configPath = item.split('.');
        // app_observable.ntopo
        configPath.shift();
        console.log(configPath);
        extraAppObserverRoute.push({
          path: `/${configPath.join('/')}`,
          component: appobserver_component
        })
      });

      // Request services list, used to disable not running services
      return requestURL("/api/v1/monitor/services/list")
    })
    .then(res => {
      if (res.code == 0) {
        for (let k in res.data) {
          if (res.data[k] > 0) {
            enable_services.push(k)
          }
        }
      }
      oldRender();
    })
    .catch(err => {
      console.log(err);
      oldRender();
    })
}
